Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


electron/main.js v4.6.0-rc.4 (421126e8) Text, 30.99 KB

Tff7b72const Tb4b4b4{
Te6edf3appTb4b4b4,
Te6edf3BrowserWindowTb4b4b4,
Te6edf3dialogTb4b4b4,
Te6edf3ipcMainTb4b4b4,
Te6edf3shellTb4b4b4,
Te6edf3systemPreferencesTb4b4b4,
Te6edf3TrayTb4b4b4,
Te6edf3MenuTb4b4b4,
Te6edf3NotificationTb4b4b4,
Te6edf3powerSaveBlockerTb4b4b4,
Te6edf3sessionTb4b4b4,
Te6edf3clipboardTb4b4b4,
Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"electron"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3electronPrompt Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"electron-prompt"Tb4b4b4)Tb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3spawn Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"child_process"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3fs Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"fs"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3path Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"node:path"Tb4b4b4)Tb4b4b4;

Tff7b72const Tb4b4b4{ Te6edf3verifyBackendIntegrity Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"./backendIntegrity"Tb4b4b4)Tb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3getUserProvidedArgumentsTb4b4b4, Te6edf3formatRenderProcessGoneDetailsTb4b4b4, Te6edf3isLocalBackendUrl Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"./mainHelpers"Tb4b4b4)Tb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3isAllowedShellPath Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"./shellPathGuard"Tb4b4b4)Tb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3normalizeExternalUrlForOpen Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"./safeExternalUrl"Tb4b4b4)Tb4b4b4;

T8b949e// remember main window
Tff7b72var Te6edf3mainWindow Tff7b72= Tff7b72nullTb4b4b4;

Tff7b72function Te6edf3getDialogParentWindowTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3focused Tff7b72= Te6edf3BrowserWindowTb4b4b4.Te6edf3getFocusedWindowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3focused Tff7b72&& Tff7b72!Te6edf3focusedTb4b4b4.Te6edf3isDestroyedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3focusedTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3mainWindow Tff7b72&& Tff7b72!Te6edf3mainWindowTb4b4b4.Te6edf3isDestroyedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3mainWindowTb4b4b4;
Tb4b4b4}
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}

T8b949e// tray instance
Tff7b72var Te6edf3tray Tff7b72= Tff7b72nullTb4b4b4;

T8b949e// power save blocker id
Tff7b72var Te6edf3activePowerSaveBlockerId Tff7b72= Tff7b72nullTb4b4b4;

T8b949e// track if we are actually quiting
Tff7b72var Te6edf3isQuiting Tff7b72= Tff7b72falseTb4b4b4;

T8b949e// remember child process for exe so we can kill it when app exits
Tff7b72var Te6edf3exeChildProcess Tff7b72= Tff7b72nullTb4b4b4;
Tff7b72var Te6edf3backendRuntimeState Tff7b72= Tb4b4b4{
Te6edf3startedTff7b72: Tff7b72falseTb4b4b4,
Te6edf3runningTff7b72: Tff7b72falseTb4b4b4,
Te6edf3pidTff7b72: Tff7b72nullTb4b4b4,
Te6edf3lastExitCodeTff7b72: Tff7b72nullTb4b4b4,
Te6edf3lastErrorTff7b72: Ta5d6ff""Tb4b4b4,
Te6edf3lastEventAtTff7b72: Tff7b72nullTb4b4b4,
Tb4b4b4}Tb4b4b4;

T8b949e// store integrity status
Tff7b72var Te6edf3integrityStatus Tff7b72= Tb4b4b4{
Te6edf3backendTff7b72: Tb4b4b4{ Te6edf3okTff7b72: Tff7b72trueTb4b4b4, Te6edf3issuesTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Te6edf3dataTff7b72: Tb4b4b4{ Te6edf3okTff7b72: Tff7b72trueTb4b4b4, Te6edf3issuesTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;

T8b949e// Check for hardware acceleration preference in storage dir
Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3storageDir Tff7b72= Te6edf3getDefaultStorageDirTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3disableGpuFile Tff7b72= Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3storageDirTb4b4b4, Ta5d6ff"disable-gpu"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fsTb4b4b4.Te6edf3existsSyncTb4b4b4(Te6edf3disableGpuFileTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3disableHardwareAccelerationTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Ta5d6ff"Hardware acceleration disabled via storage flag."Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4{
T8b949e// ignore errors reading storage dir this early
Tb4b4b4}

T8b949e// Handle hardware acceleration disabling via CLI
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3argvTb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"--disable-gpu"Tb4b4b4) Tff7b72|| Te6edf3processTb4b4b4.Te6edf3argvTb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"--disable-software-rasterizer"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3disableHardwareAccelerationTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"linux"Tb4b4b4) Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3setNameTb4b4b4(Ta5d6ff"reticulum-meshchatx"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// Detect if running in Flatpak sandbox
Tff7b72const Te6edf3isRunningInFlatpak Tff7b72= Tff7b72!Tff7b72!Te6edf3processTb4b4b4.Te6edf3envTb4b4b4.Te6edf3FLATPAK_IDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3isRunningInFlatpakTb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Ta5d6ff`Ta5d6ffRunning in Flatpak sandbox: Tffd700${Te6edf3processTb4b4b4.Te6edf3envTb4b4b4.Te6edf3FLATPAK_IDTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// Protocol registration
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3defaultAppTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3argvTb4b4b4.Te6edf3length Tff7b72>= T79c0ff2Tb4b4b4) Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3setAsDefaultProtocolClientTb4b4b4(Ta5d6ff"lxmf"Tb4b4b4, Te6edf3processTb4b4b4.Te6edf3execPathTb4b4b4, Tb4b4b4[Te6edf3pathTb4b4b4.Te6edf3resolveTb4b4b4(Te6edf3processTb4b4b4.Te6edf3argvTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)Tb4b4b4]Tb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3setAsDefaultProtocolClientTb4b4b4(Ta5d6ff"rns"Tb4b4b4, Te6edf3processTb4b4b4.Te6edf3execPathTb4b4b4, Tb4b4b4[Te6edf3pathTb4b4b4.Te6edf3resolveTb4b4b4(Te6edf3processTb4b4b4.Te6edf3argvTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3setAsDefaultProtocolClientTb4b4b4(Ta5d6ff"lxmf"Tb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3setAsDefaultProtocolClientTb4b4b4(Ta5d6ff"rns"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// Single instance lock
Tff7b72const Te6edf3gotTheLock Tff7b72= Te6edf3appTb4b4b4.Te6edf3requestSingleInstanceLockTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3gotTheLockTb4b4b4) Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"second-instance"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3commandLineTb4b4b4) Tb4b4b4=> Tb4b4b4{
T8b949e// Someone tried to run a second instance, we should focus our window.
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4.Te6edf3isMinimizedTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3mainWindowTb4b4b4.Te6edf3restoreTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3mainWindowTb4b4b4.Te6edf3showTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3mainWindowTb4b4b4.Te6edf3focusTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// Handle protocol links from second instance
Tff7b72const Te6edf3url Tff7b72= Te6edf3commandLineTb4b4b4.Te6edf3popTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3url Tff7b72&& Tb4b4b4(Te6edf3urlTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"lxmf://"Tb4b4b4) Tff7b72|| Te6edf3urlTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"rns://"Tb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3sendTb4b4b4(Ta5d6ff"open-protocol-link"Tb4b4b4, Te6edf3urlTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// Handle protocol links on macOS
Te6edf3appTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"open-url"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3urlTb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3eventTb4b4b4.Te6edf3preventDefaultTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4) Tb4b4b4{
Te6edf3mainWindowTb4b4b4.Te6edf3showTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3sendTb4b4b4(Ta5d6ff"open-protocol-link"Tb4b4b4, Te6edf3urlTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// allow fetching app version via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"app-version"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3appTb4b4b4.Te6edf3getVersionTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// allow fetching hardware acceleration status via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"is-hardware-acceleration-enabled"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3appTb4b4b4.Te6edf3isHardwareAccelerationEnabledTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// allow fetching integrity status
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"get-integrity-status"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3integrityStatusTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// Native Notification IPC
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"show-notification"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Tb4b4b4{ Te6edf3titleTb4b4b4, Te6edf3bodyTb4b4b4, Te6edf3silent Tb4b4b4}Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3notification Tff7b72= Tff7b72new Te6edf3NotificationTb4b4b4(Tb4b4b4{
Te6edf3titleTff7b72: Te6edf3titleTb4b4b4,
Te6edf3bodyTff7b72: Te6edf3bodyTb4b4b4,
Te6edf3silentTff7b72: Te6edf3silentTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3notificationTb4b4b4.Te6edf3showTb4b4b4(Tb4b4b4)Tb4b4b4;

Te6edf3notificationTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"click"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4) Tb4b4b4{
Te6edf3mainWindowTb4b4b4.Te6edf3showTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3mainWindowTb4b4b4.Te6edf3focusTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// Power Management IPC
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"set-power-save-blocker"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3enabledTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3enabledTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3activePowerSaveBlockerId Tff7b72=== Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3activePowerSaveBlockerId Tff7b72= Te6edf3powerSaveBlockerTb4b4b4.Te6edf3startTb4b4b4(Ta5d6ff"prevent-app-suspension"Tb4b4b4)Tb4b4b4;
Te6edf3logTb4b4b4(Ta5d6ff"Power save blocker started."Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3activePowerSaveBlockerId Tff7b72!== Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3powerSaveBlockerTb4b4b4.Te6edf3stopTb4b4b4(Te6edf3activePowerSaveBlockerIdTb4b4b4)Tb4b4b4;
Te6edf3activePowerSaveBlockerId Tff7b72= Tff7b72nullTb4b4b4;
Te6edf3logTb4b4b4(Ta5d6ff"Power save blocker stopped."Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3activePowerSaveBlockerId Tff7b72!== Tff7b72nullTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// ignore ssl errors
Te6edf3appTb4b4b4.Te6edf3commandLineTb4b4b4.Te6edf3appendSwitchTb4b4b4(Ta5d6ff"ignore-certificate-errors"Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"backend-http-only"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3getUserProvidedArgumentsTb4b4b4(Te6edf3processTb4b4b4.Te6edf3argvTb4b4b4)Tb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"--no-https"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"backend-runtime-state"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3isRunning Tff7b72=
Tff7b72!Tff7b72!Te6edf3exeChildProcess Tff7b72&&
Te6edf3exeChildProcessTb4b4b4.Te6edf3exitCode Tff7b72=== Tff7b72null Tff7b72&&
Te6edf3exeChildProcessTb4b4b4.Te6edf3signalCode Tff7b72=== Tff7b72null Tff7b72&&
Te6edf3backendRuntimeStateTb4b4b4.Te6edf3startedTb4b4b4;
Tff7b72return Tb4b4b4{
Tb4b4b4...Te6edf3backendRuntimeStateTb4b4b4,
Te6edf3runningTff7b72: Te6edf3isRunningTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// add support for showing an alert window via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"alert"Tb4b4b4, Tff7b72async Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3messageTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showMessageBoxTb4b4b4(Te6edf3mainWindowTb4b4b4, Tb4b4b4{
Te6edf3messageTff7b72: Te6edf3messageTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// add support for showing a confirm window via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"confirm"Tb4b4b4, Tff7b72async Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3messageTb4b4b4) Tb4b4b4=> Tb4b4b4{
T8b949e// show confirm dialog
Tff7b72const Te6edf3result Tff7b72= Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showMessageBoxTb4b4b4(Te6edf3mainWindowTb4b4b4, Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"question"Tb4b4b4,
Te6edf3titleTff7b72: Ta5d6ff"Confirm"Tb4b4b4,
Te6edf3messageTff7b72: Te6edf3messageTb4b4b4,
Te6edf3cancelIdTff7b72: T79c0ff0Tb4b4b4, T8b949e// esc key should press cancel button
Te6edf3defaultIdTff7b72: T79c0ff1Tb4b4b4, T8b949e// enter key should press ok button
Te6edf3buttonsTff7b72: Tb4b4b4[
Ta5d6ff"Cancel"Tb4b4b4, T8b949e// 0
Ta5d6ff"OK"Tb4b4b4, T8b949e// 1
Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// check if user clicked OK
Tff7b72return Te6edf3resultTb4b4b4.Te6edf3response Tff7b72=== T79c0ff1Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// add support for showing a prompt window via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"prompt"Tb4b4b4, Tff7b72async Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3messageTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Tff7b72await Te6edf3electronPromptTb4b4b4(Tb4b4b4{
Te6edf3titleTff7b72: Te6edf3messageTb4b4b4,
Te6edf3labelTff7b72: Ta5d6ff""Tb4b4b4,
Te6edf3valueTff7b72: Ta5d6ff""Tb4b4b4,
Te6edf3typeTff7b72: Ta5d6ff"input"Tb4b4b4,
Te6edf3inputAttrsTff7b72: Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"text"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// allow relaunching app via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"relaunch"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3relaunchOptions Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3processTb4b4b4.Te6edf3defaultApp Tff7b72&& Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"linux" Tff7b72&& Te6edf3processTb4b4b4.Te6edf3envTb4b4b4.Te6edf3APPIMAGETb4b4b4) Tb4b4b4{
Te6edf3relaunchOptionsTb4b4b4.Te6edf3execPath Tff7b72= Te6edf3processTb4b4b4.Te6edf3envTb4b4b4.Te6edf3APPIMAGETb4b4b4;
Tb4b4b4}
Te6edf3appTb4b4b4.Te6edf3relaunchTb4b4b4(Te6edf3relaunchOptionsTb4b4b4)Tb4b4b4;
Te6edf3isQuiting Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"relaunch-emergency"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3relaunchOptions Tff7b72= Tb4b4b4{
Te6edf3argsTff7b72: Te6edf3processTb4b4b4.Te6edf3argvTb4b4b4.Te6edf3sliceTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4.Te6edf3concatTb4b4b4(Tb4b4b4[Ta5d6ff"--emergency"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3processTb4b4b4.Te6edf3defaultApp Tff7b72&& Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"linux" Tff7b72&& Te6edf3processTb4b4b4.Te6edf3envTb4b4b4.Te6edf3APPIMAGETb4b4b4) Tb4b4b4{
Te6edf3relaunchOptionsTb4b4b4.Te6edf3execPath Tff7b72= Te6edf3processTb4b4b4.Te6edf3envTb4b4b4.Te6edf3APPIMAGETb4b4b4;
Tb4b4b4}
Te6edf3appTb4b4b4.Te6edf3relaunchTb4b4b4(Te6edf3relaunchOptionsTb4b4b4)Tb4b4b4;
Te6edf3isQuiting Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"shutdown"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3isQuiting Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"get-memory-usage"Tb4b4b4, Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3processTb4b4b4.Te6edf3getProcessMemoryInfoTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// allow showing a file path in os file manager
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"showPathInFolder"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3targetPathTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3ctx Tff7b72= Tb4b4b4{
Te6edf3appTb4b4b4,
Te6edf3getDefaultStorageDirTb4b4b4,
Te6edf3getDefaultReticulumConfigDirTb4b4b4,
Te6edf3getUserProvidedArgumentsTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isAllowedShellPathTb4b4b4(Te6edf3targetPathTb4b4b4, Te6edf3ctxTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3warnTb4b4b4(Ta5d6ff"showPathInFolder denied (path outside allowed directories)"Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Te6edf3shellTb4b4b4.Te6edf3showItemInFolderTb4b4b4(Te6edf3targetPathTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"open-path"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3targetPathTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3ctx Tff7b72= Tb4b4b4{
Te6edf3appTb4b4b4,
Te6edf3getDefaultStorageDirTb4b4b4,
Te6edf3getDefaultReticulumConfigDirTb4b4b4,
Te6edf3getUserProvidedArgumentsTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isAllowedShellPathTb4b4b4(Te6edf3targetPathTb4b4b4, Te6edf3ctxTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3warnTb4b4b4(Ta5d6ff"open-path denied (path outside allowed directories)"Tb4b4b4)Tb4b4b4;
Tff7b72return Ta5d6ff"Path is not allowed"Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3shellTb4b4b4.Te6edf3openPathTb4b4b4(Te6edf3targetPathTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"pick-file"Tb4b4b4, Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3win Tff7b72= Te6edf3getDialogParentWindowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3winTb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72const Tb4b4b4{ Te6edf3canceledTb4b4b4, Te6edf3filePaths Tb4b4b4} Tff7b72= Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showOpenDialogTb4b4b4(Te6edf3winTb4b4b4, Tb4b4b4{
Te6edf3propertiesTff7b72: Tb4b4b4[Ta5d6ff"openFile"Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3canceled Tff7b72|| Tff7b72!Te6edf3filePaths Tff7b72|| Te6edf3filePathsTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3filePathsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"pick-directory"Tb4b4b4, Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3win Tff7b72= Te6edf3getDialogParentWindowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3winTb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72const Tb4b4b4{ Te6edf3canceledTb4b4b4, Te6edf3filePaths Tb4b4b4} Tff7b72= Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showOpenDialogTb4b4b4(Te6edf3winTb4b4b4, Tb4b4b4{
Te6edf3propertiesTff7b72: Tb4b4b4[Ta5d6ff"openDirectory"Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3canceled Tff7b72|| Tff7b72!Te6edf3filePaths Tff7b72|| Te6edf3filePathsTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3filePathsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Tff7b72function Te6edf3attachDevToolsF12ShortcutTb4b4b4(Te6edf3browserWindowTb4b4b4) Tb4b4b4{
Te6edf3browserWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"before-input-event"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3inputTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3inputTb4b4b4.Te6edf3type Tff7b72!== Ta5d6ff"keyDown" Tff7b72|| Te6edf3inputTb4b4b4.Te6edf3key Tff7b72!== Ta5d6ff"F12"Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3browserWindowTb4b4b4.Te6edf3isDestroyedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Te6edf3browserWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3toggleDevToolsTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3eventTb4b4b4.Te6edf3preventDefaultTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3attachDefaultContextMenuTb4b4b4(Te6edf3browserWindowTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3webContents Tff7b72= Te6edf3browserWindowTb4b4b4.Te6edf3webContentsTb4b4b4;
Te6edf3webContentsTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"context-menu"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3paramsTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3template Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3paramsTb4b4b4.Te6edf3isEditableTb4b4b4) Tb4b4b4{
Te6edf3templateTb4b4b4.Te6edf3pushTb4b4b4(
Tb4b4b4{ Te6edf3roleTff7b72: Ta5d6ff"undo" Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3roleTff7b72: Ta5d6ff"redo" Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff"separator" Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3roleTff7b72: Ta5d6ff"cut" Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3roleTff7b72: Ta5d6ff"copy" Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3roleTff7b72: Ta5d6ff"paste" Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3roleTff7b72: Ta5d6ff"pasteAndMatchStyle" Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff"separator" Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3roleTff7b72: Ta5d6ff"selectAll" Tb4b4b4}
Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3paramsTb4b4b4.Te6edf3selectionTextTb4b4b4) Tb4b4b4{
Te6edf3templateTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{ Te6edf3roleTff7b72: Ta5d6ff"copy" Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3paramsTb4b4b4.Te6edf3misspelledWordTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3suggestions Tff7b72= Te6edf3paramsTb4b4b4.Te6edf3dictionarySuggestions Tff7b72|| Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3suggestionsTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3templateTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3templateTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff"separator" Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3suggestion Tff7b72of Te6edf3suggestionsTb4b4b4) Tb4b4b4{
Te6edf3templateTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3labelTff7b72: Te6edf3suggestionTb4b4b4,
Te6edf3clickTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3webContentsTb4b4b4.Te6edf3replaceMisspellingTb4b4b4(Te6edf3suggestionTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3templateTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3templateTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff"separator" Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3templateTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3labelTff7b72: Ta5d6ff"Add to dictionary"Tb4b4b4,
Te6edf3clickTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72void Te6edf3webContentsTb4b4b4.Te6edf3sessionTb4b4b4.Te6edf3addWordToSpellCheckerDictionaryTb4b4b4(Te6edf3paramsTb4b4b4.Te6edf3misspelledWordTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3paramsTb4b4b4.Te6edf3linkURLTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3templateTb4b4b4.Te6edf3length Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3templateTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{ Te6edf3typeTff7b72: Ta5d6ff"separator" Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3templateTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3labelTff7b72: Ta5d6ff"Open link"Tb4b4b4,
Te6edf3clickTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3safe Tff7b72= Te6edf3normalizeExternalUrlForOpenTb4b4b4(Te6edf3paramsTb4b4b4.Te6edf3linkURLTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3safeTb4b4b4) Tb4b4b4{
Te6edf3shellTb4b4b4.Te6edf3openExternalTb4b4b4(Te6edf3safeTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3templateTb4b4b4.Te6edf3pushTb4b4b4(Tb4b4b4{
Te6edf3labelTff7b72: Ta5d6ff"Copy link"Tb4b4b4,
Te6edf3clickTff7b72: Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3clipboardTb4b4b4.Te6edf3writeTextTb4b4b4(Te6edf3paramsTb4b4b4.Te6edf3linkURLTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3templateTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}

Tff7b72const Te6edf3menu Tff7b72= Te6edf3MenuTb4b4b4.Te6edf3buildFromTemplateTb4b4b4(Te6edf3templateTb4b4b4)Tb4b4b4;
Te6edf3menuTb4b4b4.Te6edf3popupTb4b4b4(Tb4b4b4{ Tffa657windowTff7b72: Te6edf3browserWindow Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3logTb4b4b4(Te6edf3messageTb4b4b4) Tb4b4b4{
T8b949e// log to stdout of this process
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3messageTb4b4b4)Tb4b4b4;

T8b949e// make sure main window exists
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3mainWindowTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}

T8b949e// make sure window is not destroyed
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4.Te6edf3isDestroyedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}

T8b949e// log to web console
Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3sendTb4b4b4(Ta5d6ff"log"Tb4b4b4, Te6edf3messageTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3getDefaultStorageDirTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3portableExecutableDir Tff7b72= Te6edf3processTb4b4b4.Te6edf3envTb4b4b4.Te6edf3PORTABLE_EXECUTABLE_DIRTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"win32" Tff7b72&& Te6edf3portableExecutableDir Tff7b72!= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3portableExecutableDirTb4b4b4, Ta5d6ff".reticulum-meshchatx"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72return Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3appTb4b4b4.Te6edf3getPathTb4b4b4(Ta5d6ff"home"Tb4b4b4)Tb4b4b4, Ta5d6ff".reticulum-meshchatx"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3getDefaultReticulumConfigDirTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// if we are running a windows portable exe, we want to use .reticulum in the portable exe dir
T8b949e// e.g if we launch "E:\Some\Path\MeshChat.exe" we want to use "E:\Some\Path\.reticulum"
Tff7b72const Te6edf3portableExecutableDir Tff7b72= Te6edf3processTb4b4b4.Te6edf3envTb4b4b4.Te6edf3PORTABLE_EXECUTABLE_DIRTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"win32" Tff7b72&& Te6edf3portableExecutableDir Tff7b72!= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3portableExecutableDirTb4b4b4, Ta5d6ff".reticulum"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// otherwise, we will fall back to using the .reticulum folder in the users home directory
T8b949e// e.g: ~/.reticulum
Tff7b72return Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3appTb4b4b4.Te6edf3getPathTb4b4b4(Ta5d6ff"home"Tb4b4b4)Tb4b4b4, Ta5d6ff".reticulum"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3getAppIconPathTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3iconPath Tff7b72= Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff"build"Tb4b4b4, Ta5d6ff"icon.png"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3fallbackIconPath Tff7b72= Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff"assets"Tb4b4b4, Ta5d6ff"images"Tb4b4b4, Ta5d6ff"logo.png"Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3fsTb4b4b4.Te6edf3existsSyncTb4b4b4(Te6edf3iconPathTb4b4b4) Tff7b72? Te6edf3iconPath Tff7b72: Te6edf3fallbackIconPathTb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3createTrayTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3tray Tff7b72= Tff7b72new Te6edf3TrayTb4b4b4(Te6edf3getAppIconPathTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3contextMenu Tff7b72= Te6edf3MenuTb4b4b4.Te6edf3buildFromTemplateTb4b4b4(Tb4b4b4[
Tb4b4b4{
Te6edf3labelTff7b72: Ta5d6ff"Show App"Tb4b4b4,
Te6edf3clickTff7b72: Tff7b72function Tb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4) Tb4b4b4{
Te6edf3mainWindowTb4b4b4.Te6edf3showTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4{
Te6edf3labelTff7b72: Ta5d6ff"Quit"Tb4b4b4,
Te6edf3clickTff7b72: Tff7b72function Tb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3isQuiting Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4]Tb4b4b4)Tb4b4b4;

Te6edf3trayTb4b4b4.Te6edf3setToolTipTb4b4b4(Ta5d6ff"Reticulum MeshChatX"Tb4b4b4)Tb4b4b4;
Te6edf3trayTb4b4b4.Te6edf3setContextMenuTb4b4b4(Te6edf3contextMenuTb4b4b4)Tb4b4b4;

Te6edf3trayTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"click"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4.Te6edf3isVisibleTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3mainWindowTb4b4b4.Te6edf3hideTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3mainWindowTb4b4b4.Te6edf3showTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3appTb4b4b4.Te6edf3whenReadyTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3thenTb4b4b4(Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"browser-window-created"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3browserWindowTb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3attachDefaultContextMenuTb4b4b4(Te6edf3browserWindowTb4b4b4)Tb4b4b4;
Te6edf3attachDevToolsF12ShortcutTb4b4b4(Te6edf3browserWindowTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// Security: Enforce CSP for all requests as a shell-level fallback
Te6edf3sessionTb4b4b4.Te6edf3defaultSessionTb4b4b4.Te6edf3webRequestTb4b4b4.Te6edf3onHeadersReceivedTb4b4b4(Tb4b4b4(Te6edf3detailsTb4b4b4, Te6edf3callbackTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3responseHeaders Tff7b72= Tb4b4b4{ Tb4b4b4...Te6edf3detailsTb4b4b4.Te6edf3responseHeaders Tb4b4b4}Tb4b4b4;

T8b949e// Define a robust fallback CSP that matches our backend's policy
Tff7b72const Te6edf3fallbackCsp Tff7b72= Tb4b4b4[
Ta5d6ff"default-src 'self'"Tb4b4b4,
Ta5d6ff"script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval' blob:"Tb4b4b4,
Ta5d6ff"style-src 'self' 'unsafe-inline'"Tb4b4b4,
Ta5d6ff"img-src 'self' data: blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://*.cartocdn.com https://tiles.openfreemap.org https://*.openfreemap.org"Tb4b4b4,
Ta5d6ff"font-src 'self' data: https://tiles.openfreemap.org https://*.openfreemap.org"Tb4b4b4,
Ta5d6ff"connect-src 'self' http://127.0.0.1:9337 https://127.0.0.1:9337 http://localhost:9337 https://localhost:9337 ws://127.0.0.1:* wss://127.0.0.1:* ws://localhost:* wss://localhost:* blob: https://*.tile.openstreetmap.org https://tile.openstreetmap.org https://nominatim.openstreetmap.org https://git.quad4.io https://*.cartocdn.com https://tiles.openfreemap.org https://*.openfreemap.org"Tb4b4b4,
Ta5d6ff"media-src 'self' blob:"Tb4b4b4,
Ta5d6ff"worker-src 'self' blob:"Tb4b4b4,
Ta5d6ff"frame-src 'self'"Tb4b4b4,
Ta5d6ff"object-src 'none'"Tb4b4b4,
Ta5d6ff"base-uri 'self'"Tb4b4b4,
Tb4b4b4]Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff"; "Tb4b4b4)Tb4b4b4;

T8b949e// If the response doesn't already have a CSP, apply our fallback
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3responseHeadersTb4b4b4[Ta5d6ff"Content-Security-Policy"Tb4b4b4] Tff7b72&& Tff7b72!Te6edf3responseHeadersTb4b4b4[Ta5d6ff"content-security-policy"Tb4b4b4]Tb4b4b4) Tb4b4b4{
Te6edf3responseHeadersTb4b4b4[Ta5d6ff"Content-Security-Policy"Tb4b4b4] Tff7b72= Tb4b4b4[Te6edf3fallbackCspTb4b4b4]Tb4b4b4;
Tb4b4b4}

Te6edf3callbackTb4b4b4(Tb4b4b4{ Te6edf3responseHeaders Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// Log Hardware Acceleration status (New in Electron 39)
Tff7b72const Te6edf3isHardwareAccelerationEnabled Tff7b72= Te6edf3appTb4b4b4.Te6edf3isHardwareAccelerationEnabledTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3logTb4b4b4(Ta5d6ff`Ta5d6ffHardware Acceleration Enabled: Tffd700${Te6edf3isHardwareAccelerationEnabledTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;

T8b949e// Create system tray
Te6edf3createTrayTb4b4b4(Tb4b4b4)Tb4b4b4;

T8b949e// get arguments passed to application, and remove the provided application path
Tff7b72const Te6edf3userProvidedArguments Tff7b72= Te6edf3getUserProvidedArgumentsTb4b4b4(Te6edf3processTb4b4b4.Te6edf3argvTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3shouldLaunchHeadless Tff7b72= Te6edf3userProvidedArgumentsTb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"--headless"Tb4b4b4)Tb4b4b4;

Tff7b72if Tb4b4b4(Tff7b72!Te6edf3shouldLaunchHeadlessTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3appIconPath Tff7b72= Te6edf3getAppIconPathTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// create browser window
Te6edf3mainWindow Tff7b72= Tff7b72new Te6edf3BrowserWindowTb4b4b4(Tb4b4b4{
Te6edf3widthTff7b72: T79c0ff1500Tb4b4b4,
Te6edf3heightTff7b72: T79c0ff800Tb4b4b4,
Te6edf3iconTff7b72: Te6edf3appIconPathTb4b4b4,
Te6edf3autoHideMenuBarTff7b72: Tff7b72trueTb4b4b4,
Te6edf3webPreferencesTff7b72: Tb4b4b4{
T8b949e// used to inject logging over ipc
Te6edf3preloadTff7b72: Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff"preload.js"Tb4b4b4)Tb4b4b4,
T8b949e// Security: disable node integration in renderer
Te6edf3nodeIntegrationTff7b72: Tff7b72falseTb4b4b4,
T8b949e// Security: enable context isolation (default in Electron 12+)
Te6edf3contextIsolationTff7b72: Tff7b72trueTb4b4b4,
T8b949e// Security: enable sandbox for additional protection
Te6edf3sandboxTff7b72: Tff7b72trueTb4b4b4,
T8b949e// Security: disable remote module (deprecated but explicit)
Te6edf3enableRemoteModuleTff7b72: Tff7b72falseTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"render-process-gone"Tb4b4b4, Tb4b4b4(Te6edf3_eventTb4b4b4, Te6edf3detailsTb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3logTb4b4b4(Ta5d6ff`Ta5d6ffRenderer process crashed: Tffd700${Te6edf3formatRenderProcessGoneDetailsTb4b4b4(Te6edf3detailsTb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"unresponsive"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3logTb4b4b4(Ta5d6ff"Renderer process became unresponsive."Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3onTb4b4b4(
Ta5d6ff"did-fail-load"Tb4b4b4,
Tff7b72async Tb4b4b4(Te6edf3_eventTb4b4b4, Te6edf3errorCodeTb4b4b4, Te6edf3errorDescriptionTb4b4b4, Te6edf3validatedURLTb4b4b4, Te6edf3isMainFrameTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isMainFrame Tff7b72|| Tff7b72!Te6edf3isLocalBackendUrlTb4b4b4(Te6edf3validatedURLTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Te6edf3logTb4b4b4(Ta5d6ff`Ta5d6ffFailed to load backend URL (Tffd700${Te6edf3errorCodeTffd700}Ta5d6ff): Tffd700${Te6edf3errorDescriptionTffd700}Ta5d6ff - Tffd700${Te6edf3validatedURLTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3mainWindow Tff7b72|| Te6edf3mainWindowTb4b4b4.Te6edf3isDestroyedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3currentUrl Tff7b72= Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3getURLTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3currentUrlTb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"loading.html"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72try Tb4b4b4{
Tff7b72await Te6edf3mainWindowTb4b4b4.Te6edf3loadFileTb4b4b4(Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff"loading.html"Tb4b4b4)Tb4b4b4, Tb4b4b4{
Te6edf3queryTff7b72: Tb4b4b4{ Te6edf3startup_errorTff7b72: Ta5d6ff"backend_unreachable" Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3errorTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Ta5d6ff`Ta5d6ffFailed to restore loading screen after backend load failure: Tffd700${Te6edf3errorTb4b4b4.Te6edf3messageTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4)Tb4b4b4;

T8b949e// minimize to tray behavior
Te6edf3mainWindowTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"close"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isQuitingTb4b4b4) Tb4b4b4{
Te6edf3eventTb4b4b4.Te6edf3preventDefaultTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3mainWindowTb4b4b4.Te6edf3hideTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// open external links in default web browser instead of electron
Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3setWindowOpenHandlerTb4b4b4(Tb4b4b4(Tb4b4b4{ Te6edf3url Tb4b4b4}Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72var Te6edf3shouldShowInNewElectronWindow Tff7b72= Tff7b72falseTb4b4b4;

T8b949e// we want to open call.html in a new electron window
T8b949e// but all other target="_blank" links should open in the system web browser
T8b949e// we don't want /rnode-flasher/index.html to open in electron, otherwise user can't select usb devices...
Tff7b72if Tb4b4b4(
Tb4b4b4(Te6edf3urlTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"http://localhost"Tb4b4b4) Tff7b72|| Te6edf3urlTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"https://localhost"Tb4b4b4)Tb4b4b4) Tff7b72&&
Te6edf3urlTb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"/call.html"Tb4b4b4)
Tb4b4b4) Tb4b4b4{
Te6edf3shouldShowInNewElectronWindow Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}

T8b949e// we want to open blob urls in a new electron window
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3urlTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"blob:"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3shouldShowInNewElectronWindow Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}

T8b949e// open in new electron window
Tff7b72if Tb4b4b4(Te6edf3shouldShowInNewElectronWindowTb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4{
Te6edf3actionTff7b72: Ta5d6ff"allow"Tb4b4b4,
Te6edf3overrideBrowserWindowOptionsTff7b72: Tb4b4b4{
Te6edf3autoHideMenuBarTff7b72: Tff7b72trueTb4b4b4,
Te6edf3webPreferencesTff7b72: Tb4b4b4{
Te6edf3preloadTff7b72: Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff"preload.js"Tb4b4b4)Tb4b4b4,
Te6edf3nodeIntegrationTff7b72: Tff7b72falseTb4b4b4,
Te6edf3contextIsolationTff7b72: Tff7b72trueTb4b4b4,
Te6edf3sandboxTff7b72: Tff7b72trueTb4b4b4,
Te6edf3enableRemoteModuleTff7b72: Tff7b72falseTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}

T8b949e// fallback to opening any other url in external browser (http(s) / mailto only)
Tff7b72const Te6edf3safe Tff7b72= Te6edf3normalizeExternalUrlForOpenTb4b4b4(Te6edf3urlTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3safeTb4b4b4) Tb4b4b4{
Te6edf3shellTb4b4b4.Te6edf3openExternalTb4b4b4(Te6edf3safeTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Tb4b4b4{
Te6edf3actionTff7b72: Ta5d6ff"deny"Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// navigate to loading page
Tff7b72await Te6edf3mainWindowTb4b4b4.Te6edf3loadFileTb4b4b4(Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff"loading.html"Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// ask mac users for microphone access for audio calls to work
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"darwin"Tb4b4b4) Tb4b4b4{
Tff7b72await Te6edf3systemPreferencesTb4b4b4.Te6edf3askForMediaAccessTb4b4b4(Ta5d6ff"microphone"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// find path to python/cxfreeze executable (setup.py builds ReticulumMeshChatX)
Tff7b72const Te6edf3exeName Tff7b72= Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"win32" Tff7b72? Ta5d6ff"ReticulumMeshChatX.exe" Tff7b72: Ta5d6ff"ReticulumMeshChatX"Tb4b4b4;

T8b949e// get app path (handles both development and packaged app)
Tff7b72const Te6edf3appPath Tff7b72= Te6edf3appTb4b4b4.Te6edf3getAppPathTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// get resources path (where extraFiles are placed)
Tff7b72const Te6edf3resourcesPath Tff7b72= Te6edf3processTb4b4b4.Te6edf3resourcesPath Tff7b72|| Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3appPathTb4b4b4, Ta5d6ff".."Tb4b4b4, Ta5d6ff".."Tb4b4b4)Tb4b4b4;
Tff7b72var Te6edf3exe Tff7b72= Tff7b72nullTb4b4b4;

Tff7b72const Te6edf3platformFolder Tff7b72=
Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"win32" Tff7b72|| Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"win"
Tff7b72? Ta5d6ff"win32"
Tff7b72: Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"darwin"
Tff7b72? Ta5d6ff"darwin"
Tff7b72: Ta5d6ff"linux"Tb4b4b4;
Tff7b72const Te6edf3archSegment Tff7b72= Tb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3arch Tff7b72=== Ta5d6ff"arm64"Tb4b4b4) Tff7b72return Ta5d6ff"arm64"Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3arch Tff7b72=== Ta5d6ff"ia32"Tb4b4b4) Tff7b72return Ta5d6ff"ia32"Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3arch Tff7b72=== Ta5d6ff"arm"Tb4b4b4) Tff7b72return Ta5d6ff"armv7l"Tb4b4b4;
Tff7b72return Ta5d6ff"x64"Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3packagedExtraResourceDir Tff7b72= Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3resourcesPathTb4b4b4, Ta5d6ff`Tffd700${Te6edf3platformFolderTffd700}Ta5d6ff-Tffd700${Te6edf3archSegmentTffd700}Ta5d6ff`Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4;

T8b949e// when packaged, extraResources are placed at resources/backend
T8b949e// when packaged with extraFiles, they were at resources/app/electron/build/exe
T8b949e// when packaged with asar, unpacked files are in app.asar.unpacked/ directory
T8b949e// app.getAppPath() returns the path to app.asar, so unpacked is at the same level
Tff7b72const Te6edf3possiblePaths Tff7b72= Tb4b4b4[
T8b949e// packaged app - extraResources location (resources/backend)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3resourcesPathTb4b4b4, Ta5d6ff"backend"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
T8b949e// @electron/packager extraResource: copies build/exe/<platform>-<arch> to resources/<platform>-<arch>/
Te6edf3packagedExtraResourceDirTb4b4b4,
T8b949e// electron-forge extraResource location (resources/exe)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3resourcesPathTb4b4b4, Ta5d6ff"exe"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
T8b949e// legacy packaged app - extraFiles location (resources/app/electron/build/exe)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3resourcesPathTb4b4b4, Ta5d6ff"app"Tb4b4b4, Ta5d6ff"electron"Tb4b4b4, Ta5d6ff"build"Tb4b4b4, Ta5d6ff"exe"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
T8b949e// packaged app with asar (unpacked files from asarUnpack)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3appPathTb4b4b4, Ta5d6ff".."Tb4b4b4, Ta5d6ff"app.asar.unpacked"Tb4b4b4, Ta5d6ff"build"Tb4b4b4, Ta5d6ff"exe"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
T8b949e// packaged app without asar (relative to app path)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3appPathTb4b4b4, Ta5d6ff"build"Tb4b4b4, Ta5d6ff"exe"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
T8b949e// development mode (relative to electron directory)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff"build"Tb4b4b4, Ta5d6ff"exe"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
T8b949e// development mode (relative to project root)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff".."Tb4b4b4, Ta5d6ff"build"Tb4b4b4, Ta5d6ff"exe"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4;

T8b949e// find the first path that exists
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3possibleExe Tff7b72of Te6edf3possiblePathsTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3fsTb4b4b4.Te6edf3existsSyncTb4b4b4(Te6edf3possibleExeTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3exe Tff7b72= Te6edf3possibleExeTb4b4b4;
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// verify executable exists
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3exe Tff7b72|| Tff7b72!Te6edf3fsTb4b4b4.Te6edf3existsSyncTb4b4b4(Te6edf3exeTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3errorMsg Tff7b72= Ta5d6ff`Ta5d6ffCould not find executable: Tffd700${Te6edf3exeNameTffd700}Ta5d6ff\nTa5d6ffChecked paths:Ta5d6ff\nTffd700${Te6edf3possiblePathsTb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff"\n"Tb4b4b4)Tffd700}Ta5d6ff\nTa5d6ff\nTa5d6ffApp path: Tffd700${Te6edf3appPathTffd700}Ta5d6ff\nTa5d6ffResources path: Tffd700${Te6edf3resourcesPathTffd700}Ta5d6ff`Tb4b4b4;
Te6edf3logTb4b4b4(Te6edf3errorMsgTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4) Tb4b4b4{
Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showMessageBoxTb4b4b4(Te6edf3mainWindowTb4b4b4, Tb4b4b4{
Te6edf3messageTff7b72: Te6edf3errorMsgTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}

Te6edf3logTb4b4b4(Ta5d6ff`Ta5d6ffFound executable at: Tffd700${Te6edf3exeTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;

T8b949e// Verify backend integrity before spawning
Tff7b72const Te6edf3exeDir Tff7b72= Te6edf3pathTb4b4b4.Te6edf3dirnameTb4b4b4(Te6edf3exeTb4b4b4)Tb4b4b4;
Te6edf3integrityStatusTb4b4b4.Te6edf3backend Tff7b72= Te6edf3verifyBackendIntegrityTb4b4b4(Te6edf3exeDirTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(
Te6edf3integrityStatusTb4b4b4.Te6edf3backendTb4b4b4.Te6edf3ok Tff7b72&&
Te6edf3integrityStatusTb4b4b4.Te6edf3backendTb4b4b4.Te6edf3issuesTb4b4b4.Te6edf3length Tff7b72=== T79c0ff1 Tff7b72&&
Te6edf3integrityStatusTb4b4b4.Te6edf3backendTb4b4b4.Te6edf3issuesTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=== Ta5d6ff"Manifest missing"
Tb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Ta5d6ff"Backend integrity manifest missing, skipping check."Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3integrityStatusTb4b4b4.Te6edf3backendTb4b4b4.Te6edf3okTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Ta5d6ff`Ta5d6ffINTEGRITY WARNING: Backend tampering detected! Issues: Tffd700${Te6edf3integrityStatusTb4b4b4.Te6edf3backendTb4b4b4.Te6edf3issuesTb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff", "Tb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72try Tb4b4b4{
T8b949e// arguments we always want to pass in
Tff7b72const Te6edf3requiredArguments Tff7b72= Tb4b4b4[
Ta5d6ff"--headless"Tb4b4b4, T8b949e// reticulum meshchatx usually launches default web browser, we don't want this when using electron
Ta5d6ff"--port"Tb4b4b4,
Ta5d6ff"9337"Tb4b4b4,
T8b949e// '--test-exception-message', 'Test Exception Message', // uncomment to test the crash dialog
Tb4b4b4]Tb4b4b4;

T8b949e// if user didn't provide reticulum config dir, we should provide it
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3userProvidedArgumentsTb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"--reticulum-config-dir"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3requiredArgumentsTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff"--reticulum-config-dir"Tb4b4b4, Te6edf3getDefaultReticulumConfigDirTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// if user didn't provide storage dir, we should provide it
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3userProvidedArgumentsTb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"--storage-dir"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3requiredArgumentsTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff"--storage-dir"Tb4b4b4, Te6edf3getDefaultStorageDirTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// spawn executable
Te6edf3exeChildProcess Tff7b72= Te6edf3spawnTb4b4b4(Te6edf3exeTb4b4b4, Tb4b4b4[
Tb4b4b4...Te6edf3requiredArgumentsTb4b4b4, T8b949e// always provide required arguments
Tb4b4b4...Te6edf3userProvidedArgumentsTb4b4b4, T8b949e// also include any user provided arguments
Tb4b4b4]Tb4b4b4)Tb4b4b4;

Tff7b72if Tb4b4b4(Tff7b72!Te6edf3exeChildProcess Tff7b72|| Tff7b72!Te6edf3exeChildProcessTb4b4b4.Te6edf3pidTb4b4b4) Tb4b4b4{
Tff7b72throw Tff7b72new Tf85149ErrorTb4b4b4(Ta5d6ff"Failed to start backend process (no PID)."Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3backendRuntimeState Tff7b72= Tb4b4b4{
Te6edf3startedTff7b72: Tff7b72trueTb4b4b4,
Te6edf3runningTff7b72: Tff7b72trueTb4b4b4,
Te6edf3pidTff7b72: Te6edf3exeChildProcessTb4b4b4.Te6edf3pidTb4b4b4,
Te6edf3lastExitCodeTff7b72: Tff7b72nullTb4b4b4,
Te6edf3lastErrorTff7b72: Ta5d6ff""Tb4b4b4,
Te6edf3lastEventAtTff7b72: Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4;

T8b949e// log stdout
Tff7b72var Te6edf3stdoutLines Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Te6edf3exeChildProcessTb4b4b4.Te6edf3stdoutTb4b4b4.Te6edf3setEncodingTb4b4b4(Ta5d6ff"utf8"Tb4b4b4)Tb4b4b4;
Te6edf3exeChildProcessTb4b4b4.Te6edf3stdoutTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"data"Tb4b4b4, Tff7b72function Tb4b4b4(Te6edf3dataTb4b4b4) Tb4b4b4{
T8b949e// log
Te6edf3logTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// keep track of last 100 stdout lines
Te6edf3stdoutLinesTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3stdoutLinesTb4b4b4.Te6edf3length Tff7b72> T79c0ff100Tb4b4b4) Tb4b4b4{
Te6edf3stdoutLinesTb4b4b4.Te6edf3shiftTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// log stderr
Tff7b72var Te6edf3stderrLines Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Te6edf3exeChildProcessTb4b4b4.Te6edf3stderrTb4b4b4.Te6edf3setEncodingTb4b4b4(Ta5d6ff"utf8"Tb4b4b4)Tb4b4b4;
Te6edf3exeChildProcessTb4b4b4.Te6edf3stderrTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"data"Tb4b4b4, Tff7b72function Tb4b4b4(Te6edf3dataTb4b4b4) Tb4b4b4{
T8b949e// log
Te6edf3logTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// keep track of last 100 stderr lines
Te6edf3stderrLinesTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3stderrLinesTb4b4b4.Te6edf3length Tff7b72> T79c0ff100Tb4b4b4) Tb4b4b4{
Te6edf3stderrLinesTb4b4b4.Te6edf3shiftTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// log errors
Te6edf3exeChildProcessTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"error"Tb4b4b4, Tff7b72function Tb4b4b4(Te6edf3errorTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Te6edf3errorTb4b4b4)Tb4b4b4;
Te6edf3backendRuntimeStateTb4b4b4.Te6edf3lastError Tff7b72= Te6edf3error Tff7b72&& Te6edf3errorTb4b4b4.Te6edf3message Tff7b72? Te6edf3errorTb4b4b4.Te6edf3message Tff7b72: Tffa657StringTb4b4b4(Te6edf3errorTb4b4b4)Tb4b4b4;
Te6edf3backendRuntimeStateTb4b4b4.Te6edf3lastEventAt Tff7b72= Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// quit electron app if exe dies
Te6edf3exeChildProcessTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"exit"Tb4b4b4, Tff7b72async Tff7b72function Tb4b4b4(Te6edf3codeTb4b4b4) Tb4b4b4{
Te6edf3backendRuntimeStateTb4b4b4.Te6edf3running Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3backendRuntimeStateTb4b4b4.Te6edf3lastExitCode Tff7b72= Te6edf3codeTb4b4b4;
Te6edf3backendRuntimeStateTb4b4b4.Te6edf3lastEventAt Tff7b72= Tffa657DateTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// if no exit code provided, we wanted exit to happen, so do nothing
Tff7b72if Tb4b4b4(Te6edf3code Tff7b72== Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}

T8b949e// show crash log
Tff7b72const Te6edf3stdout Tff7b72= Te6edf3stdoutLinesTb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff""Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3stderr Tff7b72= Te6edf3stderrLinesTb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff""Tb4b4b4)Tb4b4b4;

T8b949e// Base64 encode for safe URL passing
Tff7b72const Te6edf3stdoutBase64 Tff7b72= Te6edf3BufferTb4b4b4.Tff7b72fromTb4b4b4(Te6edf3stdoutTb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Ta5d6ff"base64"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3stderrBase64 Tff7b72= Te6edf3BufferTb4b4b4.Tff7b72fromTb4b4b4(Te6edf3stderrTb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Ta5d6ff"base64"Tb4b4b4)Tb4b4b4;

T8b949e// Load crash page if main window exists
Tff7b72if Tb4b4b4(Te6edf3mainWindow Tff7b72&& Tff7b72!Te6edf3mainWindowTb4b4b4.Te6edf3isDestroyedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3mainWindowTb4b4b4.Te6edf3showTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// Ensure visible
Te6edf3mainWindowTb4b4b4.Te6edf3focusTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3mainWindowTb4b4b4.Te6edf3loadFileTb4b4b4(Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff"crash.html"Tb4b4b4)Tb4b4b4, Tb4b4b4{
Te6edf3queryTff7b72: Tb4b4b4{
Te6edf3codeTff7b72: Te6edf3codeTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3stdoutTff7b72: Te6edf3stdoutBase64Tb4b4b4,
Te6edf3stderrTff7b72: Te6edf3stderrBase64Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Fallback for cases where window is gone
Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showMessageBoxTb4b4b4(Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"error"Tb4b4b4,
Te6edf3titleTff7b72: Ta5d6ff"MeshChatX Crashed"Tb4b4b4,
Te6edf3messageTff7b72: Ta5d6ff`Ta5d6ffBackend exited with code: Tffd700${Te6edf3codeTffd700}Ta5d6ff\nTa5d6ff\nTa5d6ffSTDOUT: Tffd700${Te6edf3stdoutTb4b4b4.Te6edf3sliceTb4b4b4(Tff7b72-T79c0ff500Tb4b4b4)Tffd700}Ta5d6ff\nTa5d6ff\nTa5d6ffSTDERR: Tffd700${Te6edf3stderrTb4b4b4.Te6edf3sliceTb4b4b4(Tff7b72-T79c0ff500Tb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3appTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"render-process-gone"Tb4b4b4, Tb4b4b4(Te6edf3_eventTb4b4b4, Te6edf3webContentsTb4b4b4, Te6edf3detailsTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3wcId Tff7b72= Te6edf3webContents Tff7b72? Te6edf3webContentsTb4b4b4.Te6edf3id Tff7b72: Ta5d6ff"unknown"Tb4b4b4;
Te6edf3logTb4b4b4(Ta5d6ff`Ta5d6ffrender-process-gone for webContents Tffd700${Te6edf3wcIdTffd700}Ta5d6ff: Tffd700${Te6edf3formatRenderProcessGoneDetailsTb4b4b4(Te6edf3detailsTb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// Track if quit has been initiated to prevent recursion
Tff7b72let Te6edf3quitInitiated Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72let Te6edf3quitTimeoutId Tff7b72= Tff7b72nullTb4b4b4;

Tff7b72function Te6edf3quitTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3quitInitiatedTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Te6edf3quitInitiated Tff7b72= Tff7b72trueTb4b4b4;

Tff7b72if Tb4b4b4(Tff7b72!Te6edf3exeChildProcessTb4b4b4) Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3exeChildProcessTb4b4b4.Te6edf3exitCode Tff7b72!== Tff7b72null Tff7b72|| Te6edf3exeChildProcessTb4b4b4.Te6edf3signalCode Tff7b72!== Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72try Tb4b4b4{
Te6edf3exeChildProcessTb4b4b4.Te6edf3killTb4b4b4(Ta5d6ff"SIGTERM"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Te6edf3exeChildProcessTb4b4b4.Te6edf3killTb4b4b4(Ta5d6ff"SIGKILL"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3e2Tb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Te6edf3e2Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3timeoutMs Tff7b72= T79c0ff5000Tb4b4b4;
Te6edf3quitTimeoutId Tff7b72= Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3exeChildProcess Tff7b72&& Te6edf3exeChildProcessTb4b4b4.Te6edf3exitCode Tff7b72=== Tff7b72null Tff7b72&& Te6edf3exeChildProcessTb4b4b4.Te6edf3signalCode Tff7b72=== Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3exeChildProcessTb4b4b4.Te6edf3killTb4b4b4(Ta5d6ff"SIGKILL"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4, Te6edf3timeoutMsTb4b4b4)Tb4b4b4;
Te6edf3exeChildProcessTb4b4b4.Te6edf3onceTb4b4b4(Ta5d6ff"exit"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3quitTimeoutIdTb4b4b4) Tb4b4b4{
Te6edf3clearTimeoutTb4b4b4(Te6edf3quitTimeoutIdTb4b4b4)Tb4b4b4;
Te6edf3quitTimeoutId Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// Handle before-quit for additional cleanup
Te6edf3appTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"before-quit"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isQuitingTb4b4b4) Tb4b4b4{
Te6edf3isQuiting Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
T8b949e// Ensure tray is destroyed to prevent it from keeping the app alive
Tff7b72if Tb4b4b4(Te6edf3tray Tff7b72&& Tff7b72!Te6edf3trayTb4b4b4.Te6edf3isDestroyedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3trayTb4b4b4.Te6edf3destroyTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3tray Tff7b72= Tff7b72nullTb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// quit electron if all windows are closed
Te6edf3appTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"window-all-closed"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────